summaryrefslogtreecommitdiff
path: root/app/api/data-room/[projectId]/files
diff options
context:
space:
mode:
Diffstat (limited to 'app/api/data-room/[projectId]/files')
-rw-r--r--app/api/data-room/[projectId]/files/route.ts246
1 files changed, 246 insertions, 0 deletions
diff --git a/app/api/data-room/[projectId]/files/route.ts b/app/api/data-room/[projectId]/files/route.ts
new file mode 100644
index 00000000..8c99c77f
--- /dev/null
+++ b/app/api/data-room/[projectId]/files/route.ts
@@ -0,0 +1,246 @@
+// app/api/data-room/[projectId]/files/route.ts
+import { NextRequest, NextResponse } from 'next/server';
+import { getServerSession } from 'next-auth/next';
+import { authOptions } from '@/app/api/auth/[...nextauth]/route';
+import { fileItems } from '@/db/schema';
+import { and, eq, isNull, desc, asc, sql } from 'drizzle-orm';
+import db from '@/db/db';
+
+// 파일 목록 조회
+export async function GET(
+ request: NextRequest,
+ { params }: { params: Promise<{ projectId: string }> }
+) {
+ try {
+ const { projectId } = await params;
+
+ // 세션 확인
+ const session = await getServerSession(authOptions);
+ if (!session?.user) {
+ return NextResponse.json({ error: '인증이 필요합니다' }, { status: 401 });
+ }
+
+ // URL 파라미터 파싱
+ const { searchParams } = new URL(request.url);
+ const parentId = searchParams.get('parentId');
+ const category = searchParams.get('category');
+ const type = searchParams.get('type'); // 'file' | 'folder' | 'all'
+ const sortBy = searchParams.get('sortBy') || 'name';
+ const sortOrder = searchParams.get('sortOrder') || 'asc';
+
+ // 기본 조회 조건 설정
+ const conditions = [];
+
+ // 프로젝트 ID는 필수
+ conditions.push(eq(fileItems.projectId, projectId));
+
+ // parentId 조건 추가
+ if (parentId && parentId !== 'null') {
+ conditions.push(eq(fileItems.parentId, parentId));
+ } else {
+ // parentId가 없으면 최상위 항목만 조회
+ conditions.push(isNull(fileItems.parentId));
+ }
+
+ // 카테고리 필터
+ if (category) {
+ conditions.push(eq(fileItems.category, category));
+ }
+
+ // 타입 필터 (file, folder, all)
+ if (type && type !== 'all') {
+ if (type === 'file' || type === 'folder') {
+ conditions.push(eq(fileItems.type, type));
+ }
+ }
+
+ // 파일 목록 조회
+ const files = await db
+ .select()
+ .from(fileItems)
+ .where(conditions.length > 0 ? and(...conditions) : undefined)
+ .orderBy(
+ // 폴더를 먼저 표시
+ desc(fileItems.type),
+ // 그 다음 정렬 기준 적용
+ sortBy === 'name'
+ ? (sortOrder === 'asc' ? asc(fileItems.name) : desc(fileItems.name))
+ : sortBy === 'updatedAt'
+ ? (sortOrder === 'asc' ? asc(fileItems.updatedAt) : desc(fileItems.updatedAt))
+ : sortBy === 'size'
+ ? (sortOrder === 'asc' ? asc(fileItems.size) : desc(fileItems.size))
+ : asc(fileItems.name) // 기본값
+ );
+
+ // 파트너사 사용자의 경우 접근 가능한 파일만 필터링
+ let filteredFiles = files;
+ if (session.user.domain === 'partners') {
+ // 현재는 모든 파일을 볼 수 있도록 설정
+ // 필요시 추가 필터링 로직 구현
+ filteredFiles = files;
+ }
+
+ // 응답 데이터 구성
+ const response = {
+ files: filteredFiles.map(file => ({
+ id: file.id,
+ projectId: file.projectId,
+ parentId: file.parentId,
+ name: file.name,
+ type: file.type,
+ path: file.path || '/',
+ category: file.category || 'uncategorized',
+ size: file.size || 0,
+ mimeType: file.mimeType || '',
+ uploadedBy: file.uploadedBy,
+ uploadedByDomain: file.uploadedByDomain || 'default',
+ createdAt: file.createdAt,
+ updatedAt: file.updatedAt,
+ // 내부 사용자에게만 추가 정보 제공
+ ...(session.user.domain !== 'partners' && {
+ createdBy: file.createdBy,
+ updatedBy: file.updatedBy,
+ }),
+ })),
+ count: filteredFiles.length,
+ parentId: parentId || null,
+ // 현재 경로 정보 (브레드크럼용)
+ currentPath: parentId ? await getCurrentPath(parentId, projectId) : [],
+ };
+
+ return NextResponse.json(response);
+
+ } catch (error) {
+ console.error('파일 목록 조회 오류:', error);
+ return NextResponse.json(
+ {
+ error: '파일 목록을 불러오는데 실패했습니다',
+ details: process.env.NODE_ENV === 'development' ? error.message : undefined
+ },
+ { status: 500 }
+ );
+ }
+}
+
+// 현재 경로 정보 가져오기 (브레드크럼용)
+async function getCurrentPath(
+ folderId: string,
+ projectId: string
+): Promise<Array<{ id: string; name: string }>> {
+ try {
+ const path: Array<{ id: string; name: string }> = [];
+ let currentId: string | null = folderId;
+ let depth = 0;
+ const maxDepth = 10;
+
+ while (currentId && depth < maxDepth) {
+ const result = await db
+ .select({
+ id: fileItems.id,
+ name: fileItems.name,
+ parentId: fileItems.parentId,
+ })
+ .from(fileItems)
+ .where(
+ and(
+ eq(fileItems.id, currentId),
+ eq(fileItems.projectId, projectId),
+ eq(fileItems.type, 'folder')
+ )
+ )
+ .limit(1);
+
+ const folder = result[0];
+ if (!folder) break;
+
+ // 경로 앞에 추가 (역순이므로)
+ path.unshift({ id: folder.id, name: folder.name });
+ currentId = folder.parentId;
+ depth++;
+ }
+
+ return path;
+ } catch (error) {
+ console.error('경로 조회 오류:', error);
+ return [];
+ }
+}
+
+// 파일 검색 (POST)
+export async function POST(
+ request: NextRequest,
+ { params }: { params: Promise<{ projectId: string }> }
+) {
+ try {
+ const { projectId } = await params;
+
+ const session = await getServerSession(authOptions);
+ if (!session?.user) {
+ return NextResponse.json({ error: '인증이 필요합니다' }, { status: 401 });
+ }
+
+ const body = await request.json();
+ const { searchTerm, filters } = body;
+
+ if (!searchTerm || searchTerm.trim().length < 2) {
+ return NextResponse.json({
+ error: '검색어는 2글자 이상 입력해주세요'
+ }, { status: 400 });
+ }
+
+ // 검색 쿼리 생성
+ const searchConditions = [
+ eq(fileItems.projectId, projectId),
+ sql`LOWER(${fileItems.name}) LIKE LOWER(${'%' + searchTerm + '%'})`
+ ];
+
+ // 필터 적용
+ if (filters?.category) {
+ searchConditions.push(eq(fileItems.category, filters.category));
+ }
+ if (filters?.type) {
+ searchConditions.push(eq(fileItems.type, filters.type));
+ }
+
+ const searchResults = await db
+ .select()
+ .from(fileItems)
+ .where(and(...searchConditions))
+ .orderBy(desc(fileItems.type), asc(fileItems.name))
+ .limit(50); // 최대 50개 결과
+
+ // 파트너사 권한 필터링
+ let filteredResults = searchResults;
+ if (session.user.domain === 'partners') {
+ // 현재는 모든 결과 반환
+ filteredResults = searchResults;
+ }
+
+ return NextResponse.json({
+ results: filteredResults.map(file => ({
+ id: file.id,
+ projectId: file.projectId,
+ parentId: file.parentId,
+ name: file.name,
+ type: file.type,
+ path: file.path || '/',
+ category: file.category || 'uncategorized',
+ size: file.size || 0,
+ mimeType: file.mimeType || '',
+ updatedAt: file.updatedAt,
+ })),
+ count: filteredResults.length,
+ searchTerm,
+ });
+
+ } catch (error) {
+ console.error('파일 검색 오류:', error);
+ return NextResponse.json(
+ {
+ error: '파일 검색에 실패했습니다',
+ details: process.env.NODE_ENV === 'development' ? error.message : undefined
+ },
+ { status: 500 }
+ );
+ }
+} \ No newline at end of file